package com.zyg.transaction;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

import com.zyg.tools.DBUtil;

public class TransactionDemo {
	
	@Test
	//正常执行，每一个sql都是一个事务，互不影响
	public void testNormal() {
		Connection connection = null;
		PreparedStatement ps = null;
		//张三转出1000
		String sql1 = "update account set balance = balance-1000 where name='张三'";
		//李四转入1000
		String sql2 = "update account set balance = balance+1000 where name='李四'";
		try {
			connection = DBUtil.getConnection();
			ps = connection.prepareStatement(sql1);
			//执行sql1,执行完之后我们手动定义一个异常
			ps.executeUpdate();
			int i = 1/0;   
			
			//此时系统执行sql2之前会报异常，sql2将不会执行，但是sql1已执行成功，
			//张三的账户已经减少1000，此时是不合理的，
			//我们应该控制转账过程中，如果发生异常，执行成功的sql执行回滚操作，由执行成功会的状态变为执行成功前的状态
			ps = connection.prepareStatement(sql2);
			ps.executeUpdate();
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			DBUtil.closeAll(connection, ps, null);
		}
	}
	
	//手动利用事务进行控制
	@Test
	public void testTransaction() {
		Connection connection = null;
		PreparedStatement ps = null;
		//张三转出1000
		String sql1 = "update account set balance = balance-1000 where name='张三'";
		//李四转入1000
		String sql2 = "update account set balance = balance+1000 where name='李四'";
		try {
			connection = DBUtil.getConnection();
			
			//如果利用java代码设置数据库隔离级别，必须在开启事务之前设置
			//connection.setTransactionIsolation(1);
			
			//开启事务，将sql1与sql2作为一组操作，将二者看为一个事务
			connection.setAutoCommit(false); // 默认值是true，也就是一个sql是一个事务
			ps = connection.prepareStatement(sql1);
			//执行sql1,执行完之后我们手动定义一个异常
			ps.executeUpdate();
			//一旦执行过程中发生异常，将执行回滚，无异常往下正常执行直到commit提交 ，可通过注释这个异常查看数据库数据变化
			int i = 1/0;
			
			//此时系统执行sql2之前会报异常，sql2将不会执行，但是sql1已执行成功，
			ps = connection.prepareStatement(sql2);
			ps.executeUpdate();
			
			connection.commit();//事务提交，此时sql1与sql2将作为一组事务，执行commit的时候数据库数据才会发生实际变化
		} catch (SQLException e) {
			//当捕获到代码执行异常时执行回滚操作
			try {
				connection.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			DBUtil.closeAll(connection, ps, null);
		}
		
	}
	
	
}
